#!/usr/bin/python -S
"""
curl_.py
"""

import os
import sys
import time
import urllib2

import tnet


class Error(Exception):
  pass


def log(msg, *args):
  if args:
    msg = msg % args
  # TODO: Sometimes when running through xmap.py, I get this -- EWOULDBLOCK.
  # Why?  Oh because in xmap.py, I capture stderr and set it to nonblocking.
  # Why doesn't that happen with stdout?  I don't have much output here, but
  # maybe it's because stderr is unbuffered?
  # File "./sleep_.py", line 25, in log
  #  print >>sys.stderr, msg
  # IOError: [Errno 11] Resource temporarily unavailable
  print >>sys.stderr, 'curl_: ' + msg


def CheckNonblocking():
  # Test to see if stdout fd is changed
  import fcntl
  fd = sys.stdout.fileno()
  flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) 
  nonblocking = flags & os.O_NONBLOCK
  log('stdout nonblocking? %s', nonblocking)


def inner_main_iter(argv):
  """
  One iteration of batch main.
  """
  log('argv %s', argv)
  CheckNonblocking()
  for url in argv:

    # Here we have a known error, which is handled.
    if url == 'BAD':
      raise Error("Got BAD")

    # Unhandled error.
    if url == 'CRASH':
      raise RuntimeError("Got CRASH")

    log('url %s', url)
    f = urllib2.urlopen(url)
    s = f.read()
    print s
    log('wrote %d bytes', len(s))
  CheckNonblocking()


def main_iter(argv):
  """Error handling wrapper."""
  try:
    inner_main_iter(argv)
    return 0
  except Error, e:
    print >> sys.stderr, e.args[0]
    return 1


def loop(argv):
  """Returns an exit code."""
  boundary = os.getenv('PGI_BOUNDARY')
  assert boundary, 'PGI_BOUNDARY required'

  pid = os.getpid()
  # Simulate slow startup.
  log('Hello from curl_.py, pid %d.  Sleeping 1 second', pid)
  time.sleep(1)

  while True:
    log('waiting for PGI input')
    try:
      request = tnet.load(sys.stdin)
    except EOFError:
      break

    # Write header
    header = {'stdout_boundary': boundary}
    sys.stdout.write(tnet.dumps(header))

    # Call main_iter
    log('got %r', request)
    argv = request['argv']
    status = main_iter(argv)
    log('status = %d', status)

    # End stdout -- WITH NEWLINE
    print boundary

    # Write trailer
    trailer = {'status': status}
    sys.stdout.write(tnet.dumps(trailer))

    sys.stdout.flush()
    log('flushed')

    # ISSUE: We could write more than we're entitled to.  I think 'waiting for
    # PGI input' is going to be lost.
    print >>sys.stderr, boundary

  return 0


def main(argv):

  CheckNonblocking()

  if os.getenv('PGI'):
    return loop(argv)
  else:
    return main_iter(argv[1:])


if __name__ == '__main__':
  sys.exit(main(sys.argv))
